﻿/*
 * @Author: Song Xinxin
 * @Date: 2022-10-30 17:46:44
 * @LastEditors: Song Xinxin
 * @LastEditTime: 2022-11-08 11:54:13
 * @FilePath: \WYW_0419_Oasis\JavaScripts\Modules\Game\Module_Game.ts
 * @Description: 游戏模块
 * 
 * Copyright (c) 2022 by error: git config user.name && git config user.email & please set dead value or install git, All Rights Reserved. 
 */
import { DataCenterS, ModuleC, ModuleManager, ModuleS, UI } from "odin";
import { Consts } from "../../Consts";
import { UIGame } from "../../UI/UIGame";
import { ModuleS_Dress } from "../Dress/Module_Dress";
import { ModuleS_NPC } from "../NPC/Module_NPC";
import { Data_PlayerAttr } from "../PlayerAttr/Data_PlayerAttr";
import { ModuleS_PlayerAttr } from "../PlayerAttr/Module_PlayerAttr";
import { ModuleS_Skill } from "../Skill/Module_Skill";
import { ModuleC_Weapon, ModuleS_Weapon } from "../Weapon/Module_Weapon";
import { Data_Game } from "./Data_Game";

//游戏模块服务端
export class ModuleS_Game extends ModuleS<ModuleC_Game,Data_Game>
{
	//已进入游戏的玩家ID及其对应的初生点位置
	PlayerBirth:Map<number,Type.Vector> = new Map();

	//游戏是否开始
	GameStart:boolean;

	//玩家ID
	IDRank:number[] = [];

	//游戏倒计时
	CountDown:number;
	//倒计时定时器
	Interval:number;

	public onAwake():void
	{
		//生成掉落死亡触发器
		this.createTrigger();
		this.GameStart = false;
	}

	public onStart(): void 
	{
		this.onPlayerLeave();
	}

	/**
     * 初始化玩家击杀数及其对应的属性的键值对
     */
	public net_initRank():void
	{
		this.currentData.initRank();
		this.currentData.saveData(true);
	}

	/**
	 * 将玩家数据根据击杀数进行降序排序
	 */
	public net_setRank():void
	{
		this.IDRank = this.sortID();
		this.setRank(this.currentData);
	}

	/**
	 * 按照ID顺序将对应的玩家数据放入数组
	 * @param data 
	 */
	public setRank(data:Data_Game):void
	{
		for(let index = 0;index < this.IDRank.length;index++)
		{
			let PlayerAttr = DataCenterS.instance.getModuleData(this.IDRank[index],Data_PlayerAttr);
			data.setNameRank(index,PlayerAttr.getName);
			data.setKillRank(index,PlayerAttr.getkill);
			data.setDeathRank(index,PlayerAttr.getdeath);
			data.setCountRank(index,PlayerAttr.getcount);
		}
		data.saveData(true);
	}

	/**
	 * 将玩家ID按照击杀数等数据进行降序排序
	 * @returns 排序后的ID数组
	 */
	public sortID():number[]
	{
		let ID:number[] = DataCenterS.instance.getPlayerIDs();
		for(let i = 0;i < ID.length - 1;i++)
		{
			for(let j = 0;j < (ID.length - i - 1);j++)
			{
				let PlayerAttr_1 = DataCenterS.instance.getModuleData(ID[j],Data_PlayerAttr);
				let PlayerAttr_2 = DataCenterS.instance.getModuleData(ID[j+1],Data_PlayerAttr);
				if(PlayerAttr_1.getkill < PlayerAttr_2.getkill)
				{
					let temp = ID[j+1];
					ID[j+1] = ID[j];
					ID[j] = temp;
				}
				else if(PlayerAttr_1.getkill == PlayerAttr_2.getkill)
				{
					if(PlayerAttr_1.getcount < PlayerAttr_2.getcount)
					{
						let temp = ID[j+1];
						ID[j+1] = ID[j];
						ID[j] = temp;
					}
					else if(PlayerAttr_1.getcount == PlayerAttr_2.getcount)
					{
						if(PlayerAttr_1.getdeath > PlayerAttr_2.getdeath)
						{
							let temp = ID[j+1];
							ID[j+1] = ID[j];
							ID[j] = temp;
						}
						else if(PlayerAttr_1.getdeath == PlayerAttr_2.getdeath)
						{
							if(PlayerAttr_1.playerId > PlayerAttr_2.playerId)
							{
								let temp = ID[j+1];
								ID[j+1] = ID[j];
								ID[j] = temp;
							}
						}
					}
				}
			}			
		}

		return ID;
	}


	/**
	 * 游戏初始化
	 */
	public net_GameStart():void
	{
		this.callClientFun(this.currentPlayer,this.client.net_initGame());
	}

	/**
	 * 初始化技能
	 */
	public net_initSkill():void
	{
		ModuleManager.instance.getModule(ModuleS_Skill).initSkill();
	}

	/**
	 * 初始化玩家属性
	 */
	public net_initPlayerAttr():void
	{
		ModuleManager.instance.getModule(ModuleS_PlayerAttr).initPlayerAttr();
	}

	/**
	 * 初始化NPC
	 */
	public net_initNPC():void
	{
		ModuleManager.instance.getModule(ModuleS_NPC).initNPC();
	}

	/**
	 * 初始化服装
	 */
	public net_sendDress():void
	{
		ModuleManager.instance.getModule(ModuleS_Dress).sendDressAll(Consts.Dress.Ragdoll.all);
	}


	/**
	 * 游戏开始
	 */
	public net_TimeStart():void
	{
		//当有一名玩家点击开始游戏按钮后游戏开始倒计时
		if(this.GameStart == false)
		{
			this.CountDown = Consts.GAME_TIME;
			this.GameStart = true;
			this.startCountDown();
		}
	}

	/**
	 * 开始倒计时
	 */
	public startCountDown():void
	{
		this.Interval = setInterval(()=>
		{
			this.CountDown--;
			Events.dispatchToAllClient("ChangeCountDown",this.CountDown);
			if(this.CountDown <= 0 )
			{
				this.GameOver();
				clearInterval(this.Interval);
			}
		},1000)
	}
	
	/**
	 * 游戏结束
	 */
	public GameOver():void
	{
		clearInterval(ModuleManager.instance.getModule(ModuleS_PlayerAttr).Interval);
		this.callWorldClientFun(this.client.net_GameOver());
		this.GameStart = false;
		this.PlayerBirth = new Map();
	}

	/**
	 * 将初生点放到随机6个位置中的一个
	 */
	public net_Birth():void
	{
		let random:number;
		let isrepeat:boolean;
		do
		{
			//随机生成0~5中的一个整数
			random = Math.floor(Math.random()*5.99999999999);
			//将初生点放到对应的位置
			this.currentPlayer.character.location = Consts.BIRTH_POSITION[random];
			//检查是否重复
			isrepeat = this.check_repeat(this.currentPlayer.character.location);
		}while(isrepeat == true);
		this.savePlayerBirth(this.currentPlayerId,this.currentPlayer.character.location);
		ModuleManager.instance.getModule(ModuleS_Weapon).createWeapon(this.currentPlayer);

	}

	//记录玩家id及其对应的初生点位置
	public savePlayerBirth(id:number,pos:Type.Vector):void
	{
		this.PlayerBirth.set(id,pos);
	}

	/**
	 * 玩家离开房间删除对应数据
	 */
	public onPlayerLeave():void
	{
		Events.addPlayerLeftListener((plaeyr:GamePlay.Player)=>
		{
			let id = plaeyr.getPlayerID();
			this.PlayerBirth.delete(id);
			this.callClientFun(plaeyr,this.client.net_destroyWeapon());

		})
	}

	/**
	 * 获取当前所有客户端玩家的服装
	 */
	public net_getDressAll():void
	{
		this.callWorldClientFun(this.client.net_getDressC(this.currentPlayer));
	}

	/**
	 * 获取调用该方法的客户端的玩家的服装
	 * @param player 进入房间的玩家
	 */
	public net_getDressS(player:GamePlay.Player):void
	{
		ModuleManager.instance.getModule(ModuleS_Dress).sendDress(player,Consts.Dress.Ragdoll.all);
	}

	/**
	 * 判断是否与已进入游戏的玩家初生点的位置重复
	 * @param loc 随机选择的初生点位置
	 * @param pos 已进入游戏的玩家的初生点位置
	 * @returns 返回判断结果
	 */
	public check_repeat(loc:Type.Vector):boolean
	{
		let isrepeat:boolean = false;
		//判断是否重复
		for(let pos of this.PlayerBirth.values())
		{
			if(loc == pos)
			{
				isrepeat = true;
				break;
			}
		}
		return isrepeat;
	}

	/**
	 *生成掉落场景外的触发器
	 */
	public async createTrigger():Promise<void>
	{
		//生成触发器
		let Trigger = await MWCore.GameObject.asyncSpawnGameObject(Consts.TRIGGER_GUID) as GamePlay.Trigger;
		Trigger.location = new Type.Vector(0,0,-1000);
		Trigger.scale = new Type.Vector(300,300,1);
		Trigger.onEnter.add((gameObject)=>
		{
			if(GamePlay.isCharacter(gameObject))
			{
				//玩家进入触发器死亡
				let player = (gameObject as GamePlay.CharacterBase).player;
				if((this.GameStart == true)&&(ModuleManager.instance.getModule(ModuleS_PlayerAttr).isDeath(player)==false))
				{
					ModuleManager.instance.getModule(ModuleS_PlayerAttr).death(player);
				}
			}
		})
	}
	
	/**
	 * 将排序后的ID发给客户端
	 */
	public net_sendIDRank()
	{
		this.callWorldClientFun(this.client.net_getIDRank(this.IDRank));
	}

}

//游戏模块客户端
export class ModuleC_Game extends ModuleC<ModuleS_Game,Data_Game>
{

	IDRank:number[] = [];

	public async onAwake():Promise<void> 
	{
		await this.currentPlayer.character.ready().then(()=>
		{
			this.server.net_sendDress();
			this.server.net_getDressAll();
		})
	}

	/**
	 * 玩家已准备好
	 */
	public PlayerReady()
	{
		this.server.net_GameStart();
	}

	/**
	 * 初始化游戏
	 */
	public net_initGame():void
	{
		this.server.net_initPlayerAttr();
		this.server.net_initNPC();
		this.server.net_initRank();
		this.server.net_initSkill();
		this.server.net_Birth();
		UI.instance.getPanel(UIGame).show_jump();
	}

	/**
	 * 游戏结束后销毁武器展示排行榜
	 */
	public net_GameOver():void
	{
		this.server.net_initSkill();
		UI.instance.getPanel(UIGame).lockSkill();
		setTimeout(()=>
		{
			ModuleManager.instance.getModule(ModuleC_Weapon).destroyweapon();
		},1000)
		this.server.net_setRank();
		this.server.net_sendIDRank();
		UI.instance.getPanel(UIGame).GameOver();
	}

	/**
	 * 销毁武器，服务端调用
	 */
	public net_destroyWeapon():void
	{
		ModuleManager.instance.getModule(ModuleC_Weapon).destroyweapon();
	}

	/**
	 * 开始计时
	 */
	public startTime():void
	{
		this.server.net_TimeStart();
	}

	/**
	 * 从服务端获取ID排名
	 * @param IDRank 
	 */
	public net_getIDRank(IDRank:number[]):void
	{
		this.IDRank = IDRank;
	}

	/**
	 * 从客户端获取ID排名
	 */
	public get getIDRank()
	{
		return this.IDRank;
	}

	/**
	 * 获取当前玩家ID
	 */
	public get getID()
	{
		return this.currentPlayerId;
	}

	/**
	 * 获取当前客户端玩家的服装
	 * @param player 进入房间的玩家
	 */
	public net_getDressC(player:GamePlay.Player):void
	{
		this.server.net_getDressS(player);
	}

}